package org.jpropelleralt.box;

import java.awt.Color;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;

import org.jpropelleralt.multiverse.Multiverse;
import org.jpropelleralt.node.Node;
import org.jpropelleralt.ref.Ref;
import org.jpropelleralt.ref.impl.RefDefault;
import org.jpropelleralt.universe.Universe;

/**
 * Static utility methods for working with {@link Boxes}
 */
public class Boxes {

	private final static Boolean trueBoolean = new Boolean(true);
	
	/**
	 * Find the user-readable, localised name for a {@link Ref} of a {@link Node}
	 * @param nodeClass		The class of {@link Node} containing the {@link Ref}
	 * @param refName		The string {@link Ref} name
	 * @return				The user readable name. This will be localised 
	 * 						as far as possible for the current {@link Locale}, 
	 * 						using resource bundles for the class name. If no 
	 * 						resource is found, the string value of the {@link Ref} name
	 * 						will be returned.
	 */
	public static String localisedName(Class<?> nodeClass, String refName) {
		try {
			ResourceBundle res = ResourceBundle.getBundle(nodeClass.getCanonicalName());
			return res.getString(refName);
		} catch (MissingResourceException mre) {
			return refName; 
		}
	}
	
	/**
	 * Find the user-readable, localised name for a class of {@link Node}
	 * @param nodeClass		The class of {@link Node}
	 * @return				The user readable class name. This will be 
	 * 						localised as far as possible for the current 
	 * 						{@link Locale}, using resource bundles for the class
	 * 						name. If no resource is found, the value of 
	 * 						{@link Class#getName()} will be returned.
	 */
	public static String localisedClassName(Class<?> nodeClass) {
		try {
			ResourceBundle res = ResourceBundle.getBundle(nodeClass.getCanonicalName());
			return res.getString("Node.Class");
		} catch (MissingResourceException mre) {
			return nodeClass.getName(); 
		}
	}
	
	/**
	 * Return true if the {@link Ref} contains
	 * a Boolean value true, false if it contains
	 * any other value, including null, or if the
	 * {@link Ref} itself is null.
	 * @param value		The {@link Ref} whose value will be checked
	 * @return			True if value is true.
	 */
	public static boolean isTrue(Ref<?> value) {
		if (value == null) {
			return false;
		}
		return trueBoolean.equals(value.get());
	}
	
	// Generic create methods
	
	/**
	 * Create a {@link Ref} with
	 * null value, and no value class.
	 * @param <T> 			The type of value
	 * @return 				A new {@link RefDefault}
	 */
	public static <T> Ref<T> create() {
		return RefDefault.create();
	}
	
	/**
	 * Create a {@link Ref} with 
	 * no value class.
	 * @param <T> 			The type of value
	 * @param value			Initial value 
	 * @return 				A new {@link RefDefault}
	 */
	public static <T> Ref<T> create(T value) {
		return RefDefault.create(value);
	}

	/**
	 * Create a {@link Ref}
	 * @param <T> 			The type of value
	 * @param valueClass	Value class 
	 * @param value			Initial value 
	 * @return 				A new {@link RefDefault}
	 */
	public static <T> Ref<T> create(Class<T> valueClass, T value) {
		return RefDefault.create(valueClass, value);
	}

	/**
	 * Create a {@link Ref}
	 * @param <T> 			The type of value
	 * @param universe		The {@link Universe} we will belong to
	 * @param valueClass	Value class 
	 * @param value			Initial value 
	 * @return 				A new {@link RefDefault}
	 */
	public static <T> Ref<T> create(Universe universe, Class<T> valueClass, T value) {
		return RefDefault.create(universe, valueClass, value);
	}
	
	// AutoCode for Boolean

	/**
	 * Create a {@link Ref} for
	 * Boolean values, in the universe
	 * given by {@link Multiverse#getCurrentUniverse()}.
	 * @param value		Initial value 
	 * @return			A new RefDefault
	 */
	public static Ref<Boolean> create(Boolean value) {
		return RefDefault.create(Boolean.class, value);
	}

	/**
	 * Create a {@link Ref} for
	 * Boolean values.
	 * @param universe		The {@link Universe} we will belong to
	 * @param value			Initial value 
	 * @return				A new RefDefault
	 */
	public static Ref<Boolean> create(Universe universe, Boolean value) {
		return RefDefault.create(universe, Boolean.class, value);
	}

// End of AutoCode for Boolean


// AutoCode for Byte

	/**
	 * Create a {@link Ref} for
	 * Byte values, in the universe
	 * given by {@link Multiverse#getCurrentUniverse()}.
	 * @param value		Initial value 
	 * @return			A new RefDefault
	 */
	public static Ref<Byte> create(Byte value) {
		return RefDefault.create(Byte.class, value);
	}

	/**
	 * Create a {@link Ref} for
	 * Byte values.
	 * @param universe		The {@link Universe} we will belong to
	 * @param value			Initial value 
	 * @return				A new RefDefault
	 */
	public static Ref<Byte> create(Universe universe, Byte value) {
		return RefDefault.create(universe, Byte.class, value);
	}

// End of AutoCode for Byte


// AutoCode for Short

	/**
	 * Create a {@link Ref} for
	 * Short values, in the universe
	 * given by {@link Multiverse#getCurrentUniverse()}.
	 * @param value		Initial value 
	 * @return			A new RefDefault
	 */
	public static Ref<Short> create(Short value) {
		return RefDefault.create(Short.class, value);
	}

	/**
	 * Create a {@link Ref} for
	 * Short values.
	 * @param universe		The {@link Universe} we will belong to
	 * @param value			Initial value 
	 * @return				A new RefDefault
	 */
	public static Ref<Short> create(Universe universe, Short value) {
		return RefDefault.create(universe, Short.class, value);
	}

// End of AutoCode for Short


// AutoCode for Integer

	/**
	 * Create a {@link Ref} for
	 * Integer values, in the universe
	 * given by {@link Multiverse#getCurrentUniverse()}.
	 * @param value		Initial value 
	 * @return			A new RefDefault
	 */
	public static Ref<Integer> create(Integer value) {
		return RefDefault.create(Integer.class, value);
	}

	/**
	 * Create a {@link Ref} for
	 * Integer values.
	 * @param universe		The {@link Universe} we will belong to
	 * @param value			Initial value 
	 * @return				A new RefDefault
	 */
	public static Ref<Integer> create(Universe universe, Integer value) {
		return RefDefault.create(universe, Integer.class, value);
	}

// End of AutoCode for Integer


// AutoCode for Long

	/**
	 * Create a {@link Ref} for
	 * Long values, in the universe
	 * given by {@link Multiverse#getCurrentUniverse()}.
	 * @param value		Initial value 
	 * @return			A new RefDefault
	 */
	public static Ref<Long> create(Long value) {
		return RefDefault.create(Long.class, value);
	}

	/**
	 * Create a {@link Ref} for
	 * Long values.
	 * @param universe		The {@link Universe} we will belong to
	 * @param value			Initial value 
	 * @return				A new RefDefault
	 */
	public static Ref<Long> create(Universe universe, Long value) {
		return RefDefault.create(universe, Long.class, value);
	}

// End of AutoCode for Long


// AutoCode for Float

	/**
	 * Create a {@link Ref} for
	 * Float values, in the universe
	 * given by {@link Multiverse#getCurrentUniverse()}.
	 * @param value		Initial value 
	 * @return			A new RefDefault
	 */
	public static Ref<Float> create(Float value) {
		return RefDefault.create(Float.class, value);
	}

	/**
	 * Create a {@link Ref} for
	 * Float values.
	 * @param universe		The {@link Universe} we will belong to
	 * @param value			Initial value 
	 * @return				A new RefDefault
	 */
	public static Ref<Float> create(Universe universe, Float value) {
		return RefDefault.create(universe, Float.class, value);
	}

// End of AutoCode for Float


// AutoCode for Double

	/**
	 * Create a {@link Ref} for
	 * Double values, in the universe
	 * given by {@link Multiverse#getCurrentUniverse()}.
	 * @param value		Initial value 
	 * @return			A new RefDefault
	 */
	public static Ref<Double> create(Double value) {
		return RefDefault.create(Double.class, value);
	}

	/**
	 * Create a {@link Ref} for
	 * Double values.
	 * @param universe		The {@link Universe} we will belong to
	 * @param value			Initial value 
	 * @return				A new RefDefault
	 */
	public static Ref<Double> create(Universe universe, Double value) {
		return RefDefault.create(universe, Double.class, value);
	}

// End of AutoCode for Double


// AutoCode for String

	/**
	 * Create a {@link Ref} for
	 * String values, in the universe
	 * given by {@link Multiverse#getCurrentUniverse()}.
	 * @param value		Initial value 
	 * @return			A new RefDefault
	 */
	public static Ref<String> create(String value) {
		return RefDefault.create(String.class, value);
	}

	/**
	 * Create a {@link Ref} for
	 * String values.
	 * @param universe		The {@link Universe} we will belong to
	 * @param value			Initial value 
	 * @return				A new RefDefault
	 */
	public static Ref<String> create(Universe universe, String value) {
		return RefDefault.create(universe, String.class, value);
	}

// End of AutoCode for String


// AutoCode for Color

	/**
	 * Create a {@link Ref} for
	 * Color values, in the universe
	 * given by {@link Multiverse#getCurrentUniverse()}.
	 * @param value		Initial value 
	 * @return			A new RefDefault
	 */
	public static Ref<Color> create(Color value) {
		return RefDefault.create(Color.class, value);
	}

	/**
	 * Create a {@link Ref} for
	 * Color values.
	 * @param universe		The {@link Universe} we will belong to
	 * @param value			Initial value 
	 * @return				A new RefDefault
	 */
	public static Ref<Color> create(Universe universe, Color value) {
		return RefDefault.create(universe, Color.class, value);
	}

// End of AutoCode for Color




	
}
